package com.beemans.corekit.integration.topon;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwner;

import com.anythink.core.api.ATAdInfo;
import com.anythink.core.api.AdError;
import com.anythink.splashad.api.ATSplashAd;
import com.anythink.splashad.api.ATSplashAdExtraInfo;
import com.anythink.splashad.api.ATSplashAdListener;
import com.anythink.splashad.api.IATSplashEyeAd;

public class SplashAdvert extends BaseAdvert implements ATSplashAdListener {
    @NonNull
    private final LifecycleOwner lifecycleOwner;
    @NonNull
    private final SplashAdvertConfig advertConfig;
    @Nullable
    private final FragmentActivity fragmentActivity;
    @Nullable
    private SplashAdvertCallback advertCallback;
    @Nullable
    private ATSplashAd atSplashAd;
    @Nullable
    private ViewGroup advertContainer;

    private boolean isAdvertLoadFailed = false;

    public SplashAdvert(
            @NonNull LifecycleOwner lifecycleOwner,
            @NonNull SplashAdvertConfig advertConfig
    ) {
        this(lifecycleOwner, advertConfig, null, null);
    }

    public SplashAdvert(
            @NonNull LifecycleOwner lifecycleOwner,
            @NonNull SplashAdvertConfig advertConfig,
            @Nullable ViewGroup advertContainer,
            @Nullable SplashAdvertCallback advertCallback
    ) {
        this.lifecycleOwner = lifecycleOwner;
        this.advertContainer = advertContainer;
        this.advertConfig = advertConfig;
        this.advertCallback = advertCallback;
        this.fragmentActivity = AdvertLifeUtils.getContext(lifecycleOwner);

        if (fragmentActivity == null) {
            return;
        }

        atSplashAd = new ATSplashAd(
                fragmentActivity,
                advertConfig.getPlacementId(),
                this,
                advertConfig.getTimeoutMillis()
        );
        atSplashAd.setAdRevenueListener(atAdInfo -> {
            if (advertCallback != null) {
                advertCallback.onAdvertRevenue(this, atAdInfo);
            }
        });

        AdvertLifeUtils.launchWhenDestroy(lifecycleOwner, this::onAdvertRelease);

        if (advertCallback != null) {
            advertCallback.onAdvertStart(this);
        }
    }

    /**
     * @return 广告是否准备完毕
     */
    @Override
    public boolean isAdvertReady() {
        if (atSplashAd == null) {
            return false;
        }
        return atSplashAd.isAdReady();
    }

    /**
     * @return 广告是否正在加载
     */
    @Override
    public boolean isAdvertLoading() {
        if (atSplashAd == null) {
            return false;
        }
        return atSplashAd.checkAdStatus().isLoading();
    }

    /**
     * 加载广告
     */
    @Override
    protected void loadAdvert() {
        loadAdvert(false);
    }

    @Override
    public void onAdvertRelease() {
        super.onAdvertRelease();

        if (advertCallback != null) {
            advertCallback = null;
        }
        if (advertContainer != null) {
            advertContainer.removeAllViews();
            advertContainer = null;
        }
        if (atSplashAd != null) {
            try {
                atSplashAd.setAdListener(null);
                atSplashAd.setAdDownloadListener(null);
                atSplashAd.setAdSourceStatusListener(null);
            } catch (Throwable ignored) {
            }
            atSplashAd = null;
        }
    }

    private void loadAdvert(boolean isPreloadAdvert) {
        isAdvertLoadFailed = false;

        if (atSplashAd == null) {
            return;
        }
        if ((!isPreloadAdvert || !advertConfig.isPreloadWithoutReady()) && isAdvertReady()) {
            onAdvertLoaded(false);
            return;
        }

        setTimeout(advertConfig.getTimeoutMillis(), () -> {
            onAdvertLoadFail(AdvertConstants.ERR_TIMEOUT_DESC);
            onAdvertRelease();
        });

        waitForAdvertToLoad(() -> {
            if (isAdvertReady()) {
                onAdvertLoaded(false);
                return;
            }
            if (atSplashAd != null) {
                onAdvertRequestPre();

                try {
                    atSplashAd.loadAd();
                } catch (Throwable throwable) {
                    onAdvertLoadFail(throwable.getMessage());
                }
            }
        });
    }

    /**
     * 展示广告
     */
    private void showAdvert() {
        if (fragmentActivity == null || advertContainer == null) {
            return;
        }
        AdvertLifeUtils.launchWhenResume(lifecycleOwner, () -> {
            if (!isAdvertReady()) {
                onAdvertShowFail();
                return;
            }
            if (advertContainer.getVisibility() != View.VISIBLE) {
                advertContainer.setVisibility(View.VISIBLE);
            }
            if (atSplashAd != null) {
                try {
                    atSplashAd.show(fragmentActivity, advertContainer);
                } catch (Throwable ignored) {
                    onAdvertShowFail();
                }
            }
        });
    }

    private void onAdvertShowFail() {
        if (advertCallback != null) {
            advertCallback.onAdvertShowFail(this);
        }
    }

    private void onAdvertRequestPre() {
        if (advertCallback != null) {
            final ATAdInfoExt adInfoExt = new ATAdInfoExt();
            adInfoExt.adunit_id = advertConfig.getPlacementId();
            adInfoExt.adunit_format = AdUnitFormat.NATIVE.getValue();
            advertCallback.onAdvertRequestPre(this, adInfoExt);
        }
    }

    private void onAdvertRequestAlt() {
        if (advertCallback != null) {
            final ATAdInfoExt adInfoExt = new ATAdInfoExt();
            adInfoExt.adunit_id = advertConfig.getPlacementId();
            adInfoExt.adunit_format = AdUnitFormat.NATIVE.getValue();
            advertCallback.onAdvertRequestAlt(this, adInfoExt);
        }
    }

    private void onAdvertLoaded(boolean adLoadedReal) {
        if (adLoadedReal) {
            onAdvertRequestAlt();
        }
        if (isAdvertLoadFailed) {
            return;
        }

        clearTimeout();

        if (advertCallback != null) {
            advertCallback.onAdvertLoaded(this);
        }
        if (advertConfig.isShowAfterLoaded()) {
            showAdvert();
        }
    }

    private void onAdvertLoadFail(String adError) {
        clearTimeout();

        if (isAdvertLoadFailed) return;
        isAdvertLoadFailed = true;

        if (advertCallback != null) {
            advertCallback.onAdvertLoadFail(this, adError);
        }
    }

    @Override
    public void onAdLoaded(boolean isTimeout) {
        if (!isTimeout) {
            onAdvertLoaded(true);
        }
    }

    @Override
    public void onAdLoadTimeout() {
        onAdvertLoadFail(AdvertConstants.ERR_TIMEOUT_DESC);
    }

    @Override
    public void onNoAdError(AdError adError) {
        onAdvertLoadFail(adError != null ? adError.toString() : null);
    }

    @Override
    public void onAdClick(ATAdInfo atAdInfo) {
        if (advertCallback != null) {
            advertCallback.onAdvertClicked(this, atAdInfo);
        }
    }

    @Override
    public void onAdShow(ATAdInfo atAdInfo) {
        if (advertCallback != null) {
            advertCallback.onAdvertShow(this, atAdInfo);
        }
        if (advertConfig.isPreloadAdvert()) {
            final SplashAdvertConfig splashAdvertConfig
                    = AdvertGsonUtils.getInstance().deepClone(advertConfig, SplashAdvertConfig.class);
            if (splashAdvertConfig != null) {
                splashAdvertConfig.setShowAfterLoaded(false);

                final SplashAdvert splashAdvert = new SplashAdvert(lifecycleOwner, splashAdvertConfig);
                splashAdvert.loadAdvert(true);
            }
        }
    }

    @Override
    public void onAdDismiss(ATAdInfo atAdInfo, ATSplashAdExtraInfo atSplashAdExtraInfo) {
        // 不展示点睛功能时调用，释放资源
        if (atSplashAdExtraInfo != null) {
            try {
                final IATSplashEyeAd eyeAd = atSplashAdExtraInfo.getAtSplashEyeAd();
                if (eyeAd != null) {
                    eyeAd.destroy();
                }
            } catch (Throwable ignored) {
            }
        }

        if (advertCallback != null) {
            advertCallback.onAdvertClose(this, atAdInfo);
        }

        onAdvertRelease();
    }
}